package com.jaws.core.common.shard.interceptor;

import com.jaws.core.common.shard.domain.SqlParseResult;
import com.jaws.core.common.shard.domain.TableShardInfo;
import com.jaws.core.common.shard.util.DruidParse;
import com.jaws.core.configuration.ShardTableProperties;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.util.List;
import java.util.Map;


/**
 * 增删改 分表逻辑处理
 *
 * @author liangqm
 * @date 2018-05-04 10:20:18
 * @since v1.0.2
 */
@Intercepts({
		@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
		@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class JawsShardSqlInterceptor extends BaseSqlInterceptor {


	public JawsShardSqlInterceptor(Map<String, ShardTableProperties.TableRule> tableRuleMap) {
		super(tableRuleMap);
	}

	@Override
	void handleNoWhereConditionsShardTable(Invocation invocation, MappedStatement mappedStatement, BoundSql boundSql, Object parameterObject, SqlParseResult sqlParseResult) throws IllegalAccessException, ClassNotFoundException {

		// 获取实际传入参数值
		List<Object> valueList = obtainInsertValues(mappedStatement, boundSql, parameterObject);

		if (sqlParseResult.getTableShardInfoMap().entrySet().isEmpty()) {
			throw new IllegalAccessException("没有分表信息");
		}

		// 获取表名
		for (Map.Entry<String, TableShardInfo> entry : sqlParseResult.getTableShardInfoMap().entrySet()) {
			String table = entry.getKey();
			TableShardInfo tableShardInfo = entry.getValue();

			// 查找分表均衡字段对应的值
			int index = tableShardInfo.getFields().lastIndexOf(tableShardInfo.getFullColumnName());
			Object value = valueList.get(index);

			// 计算分片
			String newTable = super.deduceNewTable(tableShardInfo,table,value);

			// 替换表名
			String mybatisMql = boundSql.getSql();
			String shardSql = DruidParse.replaceTable(DruidParse.obtainStatementList(mybatisMql).get(0), table, newTable);

			MappedStatement newMappedStatement = makeMappedStatement(mappedStatement, shardSql, boundSql);
			resetInvocationArgs(invocation, newMappedStatement);
		}

	}

	@Override
	void handleWhereConditionsShardTable(Invocation invocation, MappedStatement mappedStatement, BoundSql boundSql, SqlParseResult sqlParseResult) throws IllegalAccessException, ClassNotFoundException {

		if (sqlParseResult.getTableShardInfoMap().entrySet().isEmpty()) {
			throw new IllegalAccessException("没有分表信息");
		}

		// prepare mapper sql
		String mybatisSql = boundSql.getSql();

		// 获取表名
		for (Map.Entry<String, TableShardInfo> entry : sqlParseResult.getTableShardInfoMap().entrySet()) {
			String table = entry.getKey();
			TableShardInfo tableShardInfo = entry.getValue();

			// 查找分表均衡字段对应的值
			String columnMapper = tableShardInfo.getFullColumnName();
			Object value = super.obtainColumnValue(mappedStatement, boundSql, columnMapper);

			// 2.计算分片 生成新的表名
			String newTable = this.deduceNewTable(tableShardInfo,table,value);

			// 3.替换mybatis mapper sql 表名
			mybatisSql = DruidParse.replaceTable(DruidParse.obtainStatementList(mybatisSql).get(0), table, newTable);

			// 4.生成新的 MappedStatement
			MappedStatement newMappedStatement = makeMappedStatement(mappedStatement, mybatisSql, boundSql);

			// 5.将新生成的 MappedStatement 赋值给 invocation
			resetInvocationArgs(invocation, newMappedStatement);
		}
	}


}


